from numpy.random import random
from numpy.testing import assert_array_almost_equal

def standardize(x):
    """Scales a matrix so that its mean is 0 and its standard deviation is 1
    >>> 5==4
    """
    z = (x-x.mean())/x.std()
    return z, x.mean(), x.std()

def unstandardize(z, xmean, xstd):
    """Reverses standardization.
    
    >>> x = random([10])
    >>> assert_array_almost_equal(x, unstandardize(*standardize(x)))
    """
    return z*xstd + xmean

def normalize(x):
    """Scales a matrix so that it ranges from 0 to 1"""
    return (x-x.max())/(x.min()-x.max()), x.min(), x.max()

def unnormalize(y, xmin, xmax):
    """Reverses normalization.
    
    >>> x = random([10])
    >>> assert_array_almost_equal(x, unstandardize(*standardize(x)))
    """
    return y*(xmin-xmax)+xmax

def do(x):
    z, xmean, xstd = standardize(x)
    y, zmin, zmax = normalize(z)
    return y, zmin, zmax, xmean, xstd

def undo(y, zmin, zmax, xmean, xstd):
    return unstandardize(unnormalize(y, zmin, zmax), xmean, xstd)

def test():
    x = random([10000])
    assert_array_almost_equal(x, unstandardize(*standardize(x))) # Check that standardization is reversible
    assert_array_almost_equal(unnormalize(*normalize(x)), x) # Check that normalization is reversible
    assert_array_almost_equal(undo(*do(x)), x) # Check that standardization and normalization is reversible

if __name__ == '__main__':
    import doctest
    doctest.testmod()